import mail_component from "../../component/mail_component";
import { Item, MailItem } from "../../shared/face";
import { ComType } from "../tool/component";
import sdk from '../index';
import Counter, { CounterKey } from "./Counter";
import UserManager from "./UserManager";

// 邮件数据库文档接口
interface MailDocument {
    _id: string;
    title: string;
    sys: boolean; // 是否是系统邮件
    read: boolean;
    from_id: string;
    to_id: string;
    msg: string;
    items: Item[];
    send_time: number; // 发送时间
    expire_time: number; // 过期时间
    created_at: Date;
    updated_at: Date;
}

class MailManage {
    private readonly COLLECTION_NAME = 'mails';
    private readonly READ_SYSTEM_MAILS_COLLECTION = 'read_system_mails';
    
    // 内存存储
    private mailData = new Map<string, MailDocument>();
    private readSystemMails = new Map<string, Set<string>>(); // player_id -> Set<mail_id>
    private pendingMails = new Map<string, MailDocument[]>(); // 待存储的邮件
    private pendingReadRecords = new Map<string, Set<string>>(); // 待存储的系统邮件已读记录
    
    constructor() {
    }

    /**
     * 初始化邮件集合
     */
    private async initCollection() {
        try {
            const collection = sdk.db.getCollection(this.COLLECTION_NAME);
            // 创建索引以提高查询性能
            await collection.createIndex({ to_id: 1, send_time: -1 });
            await collection.createIndex({ sys: 1, expire_time: 1 });
            await collection.createIndex({ expire_time: 1 });
            console.log('邮件集合索引创建完成');

            // 初始化已读系统邮件集合
            const readSystemCollection = sdk.db.getCollection(this.READ_SYSTEM_MAILS_COLLECTION);
            await readSystemCollection.createIndex({ player_id: 1, mail_id: 1 });
            console.log('已读系统邮件集合索引创建完成');
        } catch (error) {
            console.error('创建邮件集合索引失败:', error);
        }
    }

    /**
     * 初始化邮件系统 - 加载数据到内存
     */
    async init() {
        await this.initCollection();
        try {
            // 加载所有邮件到内存
            const mails = await sdk.db.getCollection(this.COLLECTION_NAME).find({}).toArray();
            this.mailData.clear();
            mails.forEach((mail: any) => {
                this.mailData.set(mail._id, mail);
            });
            console.log(`邮件系统初始化完成，加载了 ${this.mailData.size} 封邮件到内存`);

            // 加载已读系统邮件记录到内存
            const readSystemRecords = await sdk.db.getCollection(this.READ_SYSTEM_MAILS_COLLECTION).find({}).toArray();
            this.readSystemMails.clear();
            readSystemRecords.forEach((record: any) => {
                if (!this.readSystemMails.has(record.player_id)) {
                    this.readSystemMails.set(record.player_id, new Set());
                }
                this.readSystemMails.get(record.player_id)!.add(record.mail_id);
            });
            console.log(`已读系统邮件记录加载完成，共 ${this.readSystemMails.size} 个玩家`);

            // 清理过期邮件
            await this.cleanExpiredMails();
        } catch (error) {
            console.error('邮件系统初始化失败:', error);
        }
    }

    /**
     * 清理过期邮件
     */
    private async cleanExpiredMails() {
        try {
            const currentTime = Date.now();
            const expiredMails: string[] = [];
            
            // 从内存中找出过期邮件
            for (const [mailId, mail] of this.mailData.entries()) {
                if (mail.expire_time > 0 && mail.expire_time <= currentTime) {
                    expiredMails.push(mailId);
                }
            }
            
            // 从内存中删除过期邮件
            expiredMails.forEach(mailId => {
                this.mailData.delete(mailId);
            });
            
            // 从数据库中删除过期邮件
            if (expiredMails.length > 0) {
                await sdk.db.getCollection(this.COLLECTION_NAME).deleteMany({
                    _id: { $in: expiredMails as any }
                });
                console.log(`清理了 ${expiredMails.length} 封过期邮件`);
            }
        } catch (error) {
            console.error('清理过期邮件失败:', error);
        }
    }

    /**
     * 保存邮件数据到数据库
     */
    async save() {
        try {
            // 批量存储待存储的邮件
            if (this.pendingMails.size > 0) {
                const mailsToInsert: MailDocument[] = [];
                for (const mails of this.pendingMails.values()) {
                    mailsToInsert.push(...mails);
                }
                
                if (mailsToInsert.length > 0) {
                    await sdk.db.getCollection(this.COLLECTION_NAME).insertMany(mailsToInsert as any);
                    console.log(`批量存储了 ${mailsToInsert.length} 封邮件到数据库`);
                }
                this.pendingMails.clear();
            }

            // 批量存储系统邮件已读记录
            if (this.pendingReadRecords.size > 0) {
                const readRecordsToInsert: any[] = [];
                for (const [playerId, mailIds] of this.pendingReadRecords.entries()) {
                    for (const mailId of mailIds) {
                        readRecordsToInsert.push({
                            player_id: playerId,
                            mail_id: mailId,
                            read_time: new Date()
                        });
                    }
                }
                
                if (readRecordsToInsert.length > 0) {
                    await sdk.db.getCollection(this.READ_SYSTEM_MAILS_COLLECTION).insertMany(readRecordsToInsert);
                    console.log(`批量存储了 ${readRecordsToInsert.length} 条系统邮件已读记录到数据库`);
                }
                this.pendingReadRecords.clear();
            }

            console.log('邮件数据保存完成');
        } catch (error) {
            console.error('保存邮件数据失败:', error);
        }
    }

    /**
     * 玩家拉取最新邮件 - 从内存中获取
     * @param id 玩家ID
     */
    async pull(id: string): Promise<MailItem[]> {
        try {
            const currentTime = Date.now();
            const userMails: MailItem[] = [];
            const systemMails: MailItem[] = [];
            
            // 获取玩家已读的系统邮件ID列表
            const readSystemMailIds = this.readSystemMails.get(id) || new Set();
            
            // 从内存中获取玩家的个人邮件
            for (const mail of this.mailData.values()) {
                if (mail.to_id === id && !mail.sys) {
                    if (mail.expire_time === -1 || mail.expire_time > currentTime) {
                        userMails.push(mail as unknown as MailItem);
                    }
                }
            }

            // 从内存中获取系统邮件（过滤已读的）
            for (const mail of this.mailData.values()) {
                if (mail.sys) {
                    if (mail.expire_time === -1 || mail.expire_time > currentTime) {
                        if (!readSystemMailIds.has(mail._id)) {
                            systemMails.push(mail as unknown as MailItem);
                        }
                    }
                }
            }

            // 个人邮件在查看时才删除，不在拉取时删除
            console.log(`玩家 ${id} 的个人邮件保留在内存中，共 ${userMails.length} 封`);

            // 合并邮件列表
            const mailList: MailItem[] = [...userMails, ...systemMails];
            
            console.log(`玩家 ${id} 拉取了 ${mailList.length} 封邮件 (个人: ${userMails.length}, 系统: ${systemMails.length})`);
            return mailList;
        } catch (error) {
            console.error('拉取邮件失败:', error);
            return [];
        }
    }

    /**
     * 发送邮件 - 存储到内存
     * @param from_id 发送者ID
     * @param to_id 接收者ID
     * @param time 过期时间（天数）
     * @param title 邮件标题
     * @param msg 邮件内容
     * @param item 附件
     */
     async send(from_id: string, to_id: string, time: number, title: string, msg: string, item: Item[] = []) {
        try {
            const currentTime = Date.now();
            const expireTime = time > 0 ? currentTime + 1000 * 60 * 60 * 24 * time : -1;

            const mailDoc: MailDocument = {
                _id: Counter.get(CounterKey.邮件ID),
                title: title,
                from_id: from_id,
                sys: from_id === 'sys',
                to_id: to_id,
                msg: msg,
                read: false,
                items: item,
                send_time: currentTime,
                expire_time: expireTime,
                created_at: new Date(),
                updated_at: new Date()
            };

            if (from_id === 'sys') {
                // 系统邮件 - 存储到内存并发送给所有在线玩家
                console.log('发送系统邮件');
                this.mailData.set(mailDoc._id, mailDoc);
                const list = UserManager.getPlayers();
                for (const element of list) {
                    const com = element.getComponent(ComType.邮件) as mail_component;
                    com.add(JSON.parse(JSON.stringify(mailDoc)));
                }
            } else {
                // 个人邮件 - 总是存储到内存中，确保一致性
                console.log(`玩家 ${to_id} 个人邮件，存储到内存`);
                this.mailData.set(mailDoc._id, mailDoc);
                
                // 添加到待存储队列
                if (!this.pendingMails.has(to_id)) {
                    this.pendingMails.set(to_id, []);
                }
                this.pendingMails.get(to_id)!.push(mailDoc);
                
                // 如果玩家在线，也直接发送到邮件组件
                const onlinePlayer = UserManager.getOnlinePlayer(to_id);
                if (onlinePlayer) {
                    console.log(`玩家 ${to_id} 在线，同时发送到邮件组件`);
                    const com = onlinePlayer.getComponent(ComType.邮件) as mail_component;
                    com.add(JSON.parse(JSON.stringify(mailDoc)));
                }
            }

            console.log(`邮件发送成功: ${title}`);
        } catch (error) {
            console.error('发送邮件失败:', error);
        }
    }

    /**
     * 获取玩家邮件数量 - 从内存中获取
     * @param id 玩家ID
     */
    async getMailCount(id: string): Promise<number> {
        try {
            const currentTime = Date.now();
            let userMailCount = 0;
            let unreadSystemMailCount = 0;
            
            // 获取玩家已读的系统邮件ID列表
            const readSystemMailIds = this.readSystemMails.get(id) || new Set();
            
            // 从内存中统计个人邮件数量
            for (const mail of this.mailData.values()) {
                if (mail.to_id === id && !mail.sys) {
                    if (mail.expire_time === -1 || mail.expire_time > currentTime) {
                        userMailCount++;
                    }
                }
            }

            // 从内存中统计未读系统邮件数量
            for (const mail of this.mailData.values()) {
                if (mail.sys) {
                    if (mail.expire_time === -1 || mail.expire_time > currentTime) {
                        if (!readSystemMailIds.has(mail._id)) {
                            unreadSystemMailCount++;
                        }
                    }
                }
            }

            const count = userMailCount + unreadSystemMailCount;
            console.log(`玩家 ${id} 邮件数量: ${count} (个人: ${userMailCount}, 系统: ${unreadSystemMailCount})`);
            return count;
        } catch (error) {
            console.error('获取邮件数量失败:', error);
            return 0;
        }
    }

    /**
     * 标记邮件为已读 - 在内存中处理
     * @param mailId 邮件ID
     */
    async markAsRead(mailId: string): Promise<boolean> {
        try {
            const mail = this.mailData.get(mailId);
            if (mail) {
                mail.read = true;
                mail.updated_at = new Date();
                console.log(`邮件 ${mailId} 已标记为已读`);
                return true;
            } else {
                console.log(`邮件 ${mailId} 标记已读失败，邮件可能不存在`);
                return false;
            }
        } catch (error) {
            console.error('标记邮件已读失败:', error);
            return false;
        }
    }

    /**
     * 删除邮件 - 从内存中删除
     * @param mailId 邮件ID
     */
    async deleteMail(mailId: string): Promise<boolean> {
        try {
            if (this.mailData.has(mailId)) {
                this.mailData.delete(mailId);
                console.log(`邮件 ${mailId} 删除成功`);
                return true;
            } else {
                console.log(`邮件 ${mailId} 删除失败，邮件可能不存在`);
                return false;
            }
        } catch (error) {
            console.error('删除邮件失败:', error);
            return false;
        }
    }

    /**
     * 根据ID获取邮件详情 - 从内存中获取
     * @param mailId 邮件ID
     */
    async getMailById(mailId: string): Promise<MailItem | null> {
        try {
            const mail = this.mailData.get(mailId);
            
            if (mail) {
                console.log(`获取邮件详情成功: ${mailId}`);
                return mail as unknown as MailItem;
            } else {
                console.log(`邮件不存在: ${mailId}`);
                return null;
            }
        } catch (error) {
            console.error('获取邮件详情失败:', error);
            return null;
        }
    }

    /**
     * 标记系统邮件为已读 - 在内存中处理
     * @param playerId 玩家ID
     * @param mailId 邮件ID
     */
    async markSystemMailAsRead(playerId: string, mailId: string): Promise<boolean> {
        try {
            if (!this.readSystemMails.has(playerId)) {
                this.readSystemMails.set(playerId, new Set());
            }
            this.readSystemMails.get(playerId)!.add(mailId);
            
            // 添加到待存储队列
            if (!this.pendingReadRecords.has(playerId)) {
                this.pendingReadRecords.set(playerId, new Set());
            }
            this.pendingReadRecords.get(playerId)!.add(mailId);
            
            console.log(`玩家 ${playerId} 已读系统邮件 ${mailId}`);
            return true;
        } catch (error) {
            console.error('记录系统邮件已读失败:', error);
            return false;
        }
    }
}

export default new MailManage();